package com.xlh.virtualization.websocket;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.google.gson.Gson;
import com.xlh.enums.course.VideoStatusEnum;
import com.xlh.enums.user.RoleEnum;
import com.xlh.param.course.TheoryVideoStatisticsParam;
import com.xlh.service.courseTest.TheoryService;
import com.xlh.util.SpringContextUtil;
import com.xlh.websocket.GetHttpSessionConfigurator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author sy
 * 理论课视频时长统计
 * 用于记录理论课视频的开始和停止
 */

@ServerEndpoint(value = "/ws/theory/course/videotime/{chapterId}", configurator = GetHttpSessionConfigurator.class)
@Component
@Slf4j
public class CourseTheoryVideoTimeWebsocket {


    /**
     * 理论课多步骤实验
     */
    private static final TheoryService theoryService = SpringContextUtil.getBean(TheoryService.class);

    /**
     * 存储对象
     */
    private ConcurrentHashMap<Long, TheoryVideoStatisticsParam> store = new ConcurrentHashMap();

    /**
     * 存储连接 userId , taskId, websocketList
     */
    private static Table<Long, Long, List<CourseExperimentVideoTimeWebsocket>> connectionMap = HashBasedTable.create();

    /**
     * 用户Id
     */
    private Long userId;

    /**
     * 是否为学生
     */
    private Boolean isStudent;

    /**
     * websocket 链接
     */
    private Session session;

    @OnOpen
    public void onOpen(Session session, @PathParam("chapterId") Long chapterId, EndpointConfig config) {
        this.session = session;
        this.userId = (Long) config.getUserProperties().get("userId");
        this.isStudent = Objects.equals(RoleEnum.STUDENT.getRoleCode(), config.getUserProperties().get("roleId"));

    }

    @OnMessage
    public void onMessage( String jsonStr, Session session ) {

        if(!isStudent) return;
        Gson gson=new Gson();
        TheoryVideoStatisticsParam theoryVideoStatisticsParam = gson.fromJson(jsonStr, TheoryVideoStatisticsParam.class);
        if(Objects.isNull(theoryVideoStatisticsParam) || Objects.isNull(theoryVideoStatisticsParam.getVideoTime())){
            return;
        }
        BigDecimal timeNode = new BigDecimal(Double.valueOf(System.currentTimeMillis())).subtract(theoryVideoStatisticsParam.getVideoTime());
        theoryVideoStatisticsParam.setTimeNode(timeNode);
        theoryVideoStatisticsParam.setUserId(userId);
        synchronized (CourseTheoryVideoTimeWebsocket.class) {
            // 视频状态为暂停直接进行保存
            boolean isLegal = checkParamLegal(theoryVideoStatisticsParam);
            if(isLegal){
                // 视频播放为暂停状态直接记录入库
                if(VideoStatusEnum.pause.getStatus().equals(theoryVideoStatisticsParam.getIsPlay())){
                    theoryService.saveTheoryVideoTime(theoryVideoStatisticsParam);
                }
                store.put(userId, theoryVideoStatisticsParam);
            }
        }
    }

    @OnClose
    public void onClose() {

        if(!isStudent) return;
        synchronized (CourseTheoryVideoTimeWebsocket.class) {
            // 获取最后一次存入视频状态
            TheoryVideoStatisticsParam theoryVideoStatisticsParam = store.get(userId);
            if(theoryVideoStatisticsParam != null &&
                    theoryVideoStatisticsParam.getIsPlay().equals(VideoStatusEnum.paly.getStatus())){

                BigDecimal baseTime = theoryVideoStatisticsParam.getTimeNode();
                BigDecimal videoTime = new BigDecimal(System.currentTimeMillis()).subtract(baseTime);
                theoryVideoStatisticsParam.setVideoTime(videoTime.divide(new BigDecimal(1000d)));
                boolean isLegal = checkParamLegal(theoryVideoStatisticsParam);
                if(isLegal){
                    // 计算当前视频时长
                    theoryService.saveTheoryVideoTime(theoryVideoStatisticsParam);
                }
            }
        }
    }

    /**
     * 检查存入参数是否合法
     * @param theoryVideoStatisticsParam
     * @return
     */
    private boolean checkParamLegal(TheoryVideoStatisticsParam theoryVideoStatisticsParam) {

        if(Objects.isNull(theoryVideoStatisticsParam)){
            return false;
        }
        if(Objects.isNull(theoryVideoStatisticsParam.getUserId())){
            return false;
        }
        if(Objects.isNull(theoryVideoStatisticsParam.getCourseId())){
            return false;
        }
        if(Objects.isNull(theoryVideoStatisticsParam.getChapterId())){
            return false;
        }
        if(Objects.isNull(theoryVideoStatisticsParam.getClassId())){
            return false;
        }
        if(Objects.isNull(theoryVideoStatisticsParam.getVideoSumTime())){
            return false;
        }
        if(Objects.isNull(theoryVideoStatisticsParam.getVideoTime())){
            return false;
        }
        // 视频时长不得大于视频总时长
        if(theoryVideoStatisticsParam.getVideoTime()
                .compareTo(theoryVideoStatisticsParam.getVideoSumTime()) == 1){
            return false;
        }

        return true;
    }

    public static Boolean isOnline(Long userId, Long chapterId) {
        return connectionMap.contains(userId, chapterId);
    }

}
